package com.eastcom.providor.dao;

import java.lang.reflect.Method;
import java.sql.Date;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import com.eastcom.common.db.ResultData;
import com.eastcom.common.db.SQLParameter;
import com.eastcom.common.db.ValueEntity;
import com.eastcom.common.util.StringUtil;


public abstract class AbstractDAO {

	protected static final String DAO_GET="get";
	
	protected static final String DAO_SET="set";
	
    protected final String DAO_EQUAL="equal";
	
	protected final String DAO_LIKE="like";
	
	protected final String DAO_NOT_EQUAL="<>";
	
    protected final String DAO_LOWER="<";
	
	protected final String DAO_HIGHER=">";
	
    protected final String DAO_LOWER_EQUAL="<=";
	
	protected final String DAO_HIGHER_EQUAL=">=";
	
	protected final String DAO_HOUR="hour";
	
	protected final String DAO_DAY_OF_WEEK="day_of_week";
	
	protected final String DAO_MONTH="month";
	

	static{
           
	}
	
	protected List getObjectsByResultData(ResultData rd,Class targetClass,Map fieldReflectMap) throws Exception{
		if(rd==null||fieldReflectMap==null||fieldReflectMap.isEmpty())
		    return null;
		
		List results=new ArrayList();
		while(rd.next()){
			Object object=targetClass.newInstance();
			Method method=null;
			Iterator it=fieldReflectMap.entrySet().iterator();
			while(it.hasNext()){
				Entry entry=(Entry)it.next();
				Object value=rd.getObject((String)entry.getValue());
				method=targetClass.getMethod(DAO_SET+StringUtil.setFirstCharToUpperCase((String)entry.getKey()), value.getClass());
				method.invoke(object, new Object []{value});
			}
			
			results.add(object);
		}
		
		return results;
		
	}
	
	protected SQLParameter getSQLParameter(Object object,String[] fields)throws Exception{
		if(object!=null&&fields!=null&&fields.length>0){
			SQLParameter sqlParameter=new SQLParameter();
			List entities=new ArrayList();
			sqlParameter.setValueEntities(entities);
			ValueEntity entity=null;
			
			Method method=null;
			Class clazz=object.getClass();
			for(int i=0;i<fields.length;i++){
				method=clazz.getMethod(DAO_GET+StringUtil.setFirstCharToUpperCase(fields[i]), null);
				entity=new ValueEntity();
				entity.setIndex(i+1);
				if(method.getReturnType()==java.sql.Timestamp.class)
				    entity.setColumnValue(method.invoke(object, null)==null?this.getCurrentTime():method.invoke(object, null));
				else
					entity.setColumnValue(method.invoke(object, null));
				entities.add(entity);
			}
			
			return sqlParameter;
		}
		
		return null;
	}
	
	protected boolean processConditionMapConsiderNullValue(Map condition,StringBuffer sql,String type,String allisTableName,String nullValue,boolean firstCondition){
		if(condition!=null&&!condition.isEmpty()){
			Iterator it=condition.entrySet().iterator();
			
			while(it.hasNext()){
				Entry entry=(Entry) it.next();
				if(entry.getValue()==null||"".equals(entry.getValue().toString().trim())||nullValue.equals(entry.getValue().toString().trim()))
					continue;
				
				if(firstCondition){
					firstCondition=false;
					sql.append(" where ");
				}
				else
					sql.append(" and ");
				
				if(allisTableName!=null&&!allisTableName.trim().equals(""))
				    sql.append(allisTableName+".");
				
				if(this.DAO_EQUAL.equals(type))
				    sql.append(entry.getKey()+" ='"+entry.getValue()+"'");
				else if(this.DAO_NOT_EQUAL.equals(type))
					sql.append(entry.getKey()+"<>'"+entry.getValue()+"'");
				else if(this.DAO_LIKE.equals(type))
					sql.append(entry.getKey()+" like'%"+entry.getValue()+"%'");
				else if(this.DAO_LOWER.equals(type))
					sql.append(entry.getKey()+" <'"+entry.getValue()+"'");
				else if(this.DAO_HIGHER.equals(type))
					sql.append(entry.getKey()+" >'"+entry.getValue()+"'");
				else if(this.DAO_LOWER_EQUAL.equals(type))
					sql.append(entry.getKey()+" <='"+entry.getValue()+"'");
				else if(this.DAO_HIGHER.equals(type))
					sql.append(entry.getKey()+" >='"+entry.getValue()+"'");
			}
		}
		
		return firstCondition;
	}
	
	protected boolean processConditionMap(Map condition,StringBuffer sql,String type,String allisTableName,boolean firstCondition){
		if(condition!=null&&!condition.isEmpty()){
			Iterator it=condition.entrySet().iterator();
			while(it.hasNext()){
				Entry entry=(Entry) it.next();
				if(firstCondition){
					firstCondition=false;
					sql.append(" where ");
				}
				else
					sql.append(" and ");
				
				if(allisTableName!=null&&!allisTableName.trim().equals(""))
				    sql.append(allisTableName+".");
				
				if(this.DAO_EQUAL.equals(type))
				    sql.append(entry.getKey()+" ='"+entry.getValue()+"'");
				else if(this.DAO_NOT_EQUAL.equals(type))
					sql.append(entry.getKey()+"<>'"+entry.getValue()+"'");
				else if(this.DAO_LIKE.equals(type))
					sql.append(entry.getKey()+" like'%"+entry.getValue()+"%'");
				else if(this.DAO_LOWER.equals(type))
					sql.append(entry.getKey()+" <'"+entry.getValue()+"'");
				else if(this.DAO_HIGHER.equals(type))
					sql.append(entry.getKey()+" >'"+entry.getValue()+"'");
				else if(this.DAO_LOWER_EQUAL.equals(type))
					sql.append(entry.getKey()+" <='"+entry.getValue()+"'");
				else if(this.DAO_HIGHER.equals(type))
					sql.append(entry.getKey()+" >='"+entry.getValue()+"'");
			}
		}
		
		return firstCondition;
	}
	
    protected void setParamOfObjectsInMapWithValueMap(Map objectMap,Class objectClass,String paramName,Class paramClass,Map valueMap) throws Exception{
    	if(objectMap==null||objectMap.isEmpty()||valueMap==null||valueMap.isEmpty())
    		return;
    	
    	Method method=objectClass.getMethod("set"+StringUtil.setFirstCharToUpperCase(paramName), new Class[]{paramClass});
    	
		Iterator<Entry> it=objectMap.entrySet().iterator();
		while(it.hasNext()){
			Entry entry=it.next();
			method.invoke(entry.getValue(), valueMap.get(entry.getKey()));
		}
		
	}
	
	protected void mergeSQLbyFieldIterator(StringBuffer sb,String fieldName,Class clazz,Iterator it,String param,boolean firstCondition)throws Exception{
		if(!firstCondition)
			sb.append(" and "+fieldName+" in(");
		else
			sb.append(" where "+ fieldName+" in(");
		
		Method method=clazz.getMethod("get"+StringUtil.setFirstCharToUpperCase(param), null);
		
		int i=0;
		while(it.hasNext()){
			   Object object= it.next();
			   if(i==0)
				   sb.append("'"+method.invoke(object, null)+"'");
			   else
				   sb.append(",'"+method.invoke(object, null)+"'");
			   
			   i++;
		}
		
		sb.append(")");
	}
	
	protected boolean mergeSQLWithOrConditionByFieldLst(StringBuffer sb,String fieldName,List values,boolean firstCondition)throws Exception{
		if(values==null||values.isEmpty())
			return firstCondition;
		
		if(!firstCondition)
			sb.append(" and (");
		else{
			sb.append(" where (");
			firstCondition=false;
		}
		for(int i=0;i<values.size();i++){
			if(i>0)
				sb.append(" or ");
			
			sb.append(fieldName+" like '%"+values.get(i).toString()+"%'");
		}
		
		sb.append(")");
		return firstCondition;
	}
	
	
	protected void mergeSQLbyFieldLst(StringBuffer sb,String fieldName,Class clazz,List objects,String param,boolean firstCondition)throws Exception{
		if(objects==null||objects.isEmpty())
			return;
		
		if(!firstCondition)
			sb.append(" and "+fieldName+" in(");
		else
			sb.append(" where "+ fieldName+" in(");
		
		Method method=clazz.getMethod("get"+StringUtil.setFirstCharToUpperCase(param), null);
		for(int i=0;i<objects.size();i++){
			   Object object= objects.get(i);
			   if(i==0)
				   sb.append("'"+method.invoke(object, null)+"'");
			   else
				   sb.append(",'"+method.invoke(object, null)+"'");
			   
			   if(i==objects.size()-1)
				   sb.append(")");
		
		}
	}
	
	protected boolean mergeSQLbyFieldLstWithIndex(StringBuffer sb,String fieldName,List values,int startIndex,int endIndex,boolean firstCondition){
		if(values==null||values.isEmpty()||startIndex<0||endIndex>=values.size())
			return firstCondition;
		
		if(!firstCondition)
			sb.append(" and "+fieldName+" in(");
		else
			sb.append(" where "+ fieldName+" in(");
		
		for(int i=startIndex;i<=endIndex;i++){
			   String field=(String) values.get(i).toString();
			   if(i==startIndex)
				   sb.append("'"+field+"'");
			   else
				   sb.append(",'"+field+"'");
			   
			   if(i==endIndex)
				   sb.append(")");
		
		}
		
		return false;
	}
	
	protected boolean mergeSQLbyFieldLst(StringBuffer sb,String fieldName,List values,boolean firstCondition){
		if(values==null||values.isEmpty())
			return firstCondition;
		
		if(!firstCondition)
			sb.append(" and "+fieldName+" in(");
		else
			sb.append(" where "+ fieldName+" in(");
		
		for(int i=0;i<values.size();i++){
			   String field=(String) values.get(i).toString();
			   if(i==0)
				   sb.append("'"+field.trim()+"'");
			   else
				   sb.append(",'"+field.trim()+"'");
			   
			   if(i==values.size()-1)
				   sb.append(")");
		
		}
		
		return false;
	}
	
	protected boolean mergeSQLbyFieldLst(StringBuffer sb,String fieldName,Set values,boolean firstCondition){
		if(values==null||values.isEmpty())
			return firstCondition;
		
		if(!firstCondition)
			sb.append(" and "+fieldName+" in(");
		else{
			sb.append(" where "+ fieldName+" in(");
			firstCondition=false;
		}
		
		Iterator it=values.iterator();
		int i=1;
		while(it.hasNext()){
			   Object field=(String) it.next();
			   if(field==null)
				   continue;
			   
			   field=field.toString();
			   if(i==1)
				   sb.append("'"+field+"'");
			   else
				   sb.append(",'"+field+"'");
			   
			   if(i==values.size())
				   sb.append(")");
			   
			   i++;
		
		}
		
		return firstCondition;
	}
	
	protected boolean appendNotNullDateBeforeCondition(StringBuffer sql,String fieldName,Object value,boolean firstCondition){
		if(sql==null)
			return true;
		
		if(value!=null&&!"".equals(value.toString().trim())){
			if(firstCondition){
			    sql.append(" where "+fieldName+"<=to_date('"+value+"','yyyy-mm-dd hh24:mi:ss')");
			    firstCondition=false;
			}
			else
				sql.append(" and "+fieldName+"<=to_date('"+value+"','yyyy-mm-dd hh24:mi:ss')");
		}
		
		return firstCondition;
	}
	
	protected boolean appendNotNullDateAfterCondition(StringBuffer sql,String fieldName,Object value,boolean firstCondition){
		if(sql==null)
			return true;
		
		if(value!=null&&!"".equals(value.toString().trim())){
			if(firstCondition){
			    sql.append(" where "+fieldName+">=to_date('"+value+"','yyyy-mm-dd hh24:mi:ss')");
			    firstCondition=false;
			}
			else
				sql.append(" and "+fieldName+">=to_date('"+value+"','yyyy-mm-dd hh24:mi:ss')");
		}
		
		return firstCondition;
	}
	
	protected boolean appendNotNullEqualCondition(StringBuffer sql,String fieldName,Object value,boolean firstCondition){
		if(sql==null)
			return true;
		
		if(value!=null&&!"".equals(value.toString().trim())){
			if(firstCondition){
			    sql.append(" where "+fieldName+"='"+value+"'");
			    firstCondition=false;
			}
			else
				sql.append(" and "+fieldName+"='"+value+"'");
		}
		
		return firstCondition;
	}
	
	protected boolean appendNotNullLikeCondition(StringBuffer sql,String fieldName,Object value,boolean firstCondition){
		if(sql==null)
			return true;
		
		if(value!=null&&!"".equals(value.toString().trim())){
			if(firstCondition){
			    sql.append(" where "+fieldName+"like '%"+value+"%'");
			    firstCondition=false;
			}
			else
				sql.append(" and "+fieldName+"='"+value+"'");
		}
		
		return firstCondition;
	}
	
	protected void copyParamValue(Object sourceobj,Object targetobj,boolean allFields) throws Exception{
		if(sourceobj==null||targetobj==null)
			return;
		
		Method [] methods=sourceobj.getClass().getMethods();
		for(int i=0;i<methods.length;i++){
			Method getmeth=methods[i];
			if(getmeth.getName().substring(0, 3).equals("get")&&!getmeth.getName().equals("getClass")){
				Object value=getmeth.invoke(sourceobj, null);
				Method setmeth=targetobj.getClass().getMethod("set"+getmeth.getName().substring(3), new Class[]{getmeth.getReturnType()});
				if(value==null||value.toString().trim().equals("")){
					if(allFields)
						setmeth.invoke(targetobj, new Object[]{value});
						
				}
				else
					setmeth.invoke(targetobj, new Object[]{value});
			}
		}
	}
	
	protected Date getCurrentDate() {
		Calendar now = Calendar.getInstance();
		return new Date(now.getTime().getTime());
	}
	
	protected Timestamp getCurrentTime() {
		Calendar now = Calendar.getInstance();
		return new Timestamp(now.getTime().getTime());
	}
	
	protected static String getStrCurrentDate(){
		Calendar cal = Calendar.getInstance();
		SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
		return fmt.format(cal.getTime());
	}
	
	protected String getStrCurrentTime(){
		Calendar cal = Calendar.getInstance();
		SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return fmt.format(cal.getTime());
	}
	
	protected String getTime(int i,String type) {
        Calendar now = Calendar.getInstance();
        if("minute".equals(type))
        	now.add(Calendar.MINUTE, i);
        if(this.DAO_HOUR.equals(type))
            now.add(Calendar.HOUR_OF_DAY, i);
        else if(this.DAO_DAY_OF_WEEK.equals(type))
        	now.add(Calendar.DAY_OF_YEAR, i);
        else if(this.DAO_MONTH.equals(type))
        	now.add(Calendar.MONTH, i);
        
        SimpleDateFormat fmt2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return fmt2.format(now.getTime());
    }
	
	protected Calendar getDateWithLowerUnitIntegrity(String unitType,int i){
	    Calendar calendar = Calendar.getInstance();

	    if(this.DAO_MONTH.equals(unitType)){
	    	calendar.add(Calendar.MONTH, i);
	    	calendar.set(Calendar.HOUR, 0);
	    }
	    else if(this.DAO_DAY_OF_WEEK.equals(unitType)){
	    	calendar.add(Calendar.DAY_OF_YEAR, i);
	        calendar.set(Calendar.HOUR, 12);
	    }
	    
	    calendar.set(Calendar.MINUTE, 0);
	    calendar.set(Calendar.SECOND, 0);
	    
	    return calendar;
	}
	
	public static void main(String []args){	
		System.out.println(getStrCurrentDate());
	}
	
}
